package com.example.portablefortheelderlybackground.sevice.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.portablefortheelderlybackground.common.StringCommon;
import com.example.portablefortheelderlybackground.common.key.paramsKey;
import com.example.portablefortheelderlybackground.common.redis.EmptyKeyList;
import com.example.portablefortheelderlybackground.common.redis.redisKey;
import com.example.portablefortheelderlybackground.config.userDetails.AuthThread;
import com.example.portablefortheelderlybackground.dto.scienceDto.scienceDto;
import com.example.portablefortheelderlybackground.mapper.scienceMapper;
import com.example.portablefortheelderlybackground.pojo.science.science;
import com.example.portablefortheelderlybackground.pojo.science.scienceImages;
import com.example.portablefortheelderlybackground.sevice.scienceImagesService;
import com.example.portablefortheelderlybackground.sevice.scienceService;
import com.example.portablefortheelderlybackground.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.portablefortheelderlybackground.Enum.Message.ReturnMessageEnum.NOT_FOUNT;
import static com.example.portablefortheelderlybackground.Enum.Message.ReturnMessageEnum.SUCCESS;

@Service
@Slf4j
@Transactional
public class scienceServiceImpl extends ServiceImpl<scienceMapper, science> implements scienceService {
    private final
    scienceImagesService scienceImagesService;

    private final
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public scienceServiceImpl(RedisTemplate<String, Object> redisTemplate, scienceImagesService scienceImagesService) {
        this.redisTemplate = redisTemplate;
        this.scienceImagesService = scienceImagesService;
    }

    @Override
    public Response<Page<scienceDto>> getAllScienceMessage(Integer pages, Integer pageSize, String type, String title) {
        //根据type和title生成redisKeyWord
        String redisKeyWordKey = redisKey.getScienceQueryKeyByTypeAndTitle(type, title);
        //先判断队列是否存在该key
        if (EmptyKeyList.isExist(redisKey.scienceQueryKey + redisKeyWordKey + pages)) {
            //如果存在,则直接返回
            return Response.status(null, SUCCESS.getCode(), SUCCESS.getMessage());
        }
        Page<scienceDto> redisScienceDto = (Page<scienceDto>) redisTemplate.opsForValue().get(redisKey.scienceQueryKey + redisKeyWordKey + pages);
        if (!ObjectUtils.isEmpty(redisScienceDto)) {
            return Response.success(redisScienceDto, "查询成功");
        }
        IPage<science> scienceIPage = new Page<>(pages, pageSize);
        LambdaQueryWrapper<science> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(StringUtils.hasText(type), science::getType, type);
        lambdaQueryWrapper.like(StringUtils.hasText(title), science::getTitle, title);
        lambdaQueryWrapper.orderByAsc(science::getCreateTime);
        //scienceService.page(scienceIPage, lambdaQueryWrapper);
        baseMapper.selectPage(scienceIPage, lambdaQueryWrapper);
        Page<scienceDto> scienceDtoPage = new Page<>();
        BeanUtils.copyProperties(scienceIPage, scienceDtoPage, "records");
        List<scienceDto> scienceDtoList = new ArrayList<>();
        scienceDtoPage.setRecords(scienceDtoList);
        scienceIPage.getRecords().forEach(t -> {
            //创建queryWrapper
            LambdaQueryWrapper<scienceImages> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(!t.getId().isEmpty(), scienceImages::getScienceId, t.getId());
            //拿到每个查询出的scienceId
            scienceImages scienceImagesById = scienceImagesService.getOne(queryWrapper);
            //将查询出的scienceImage与t结合
            scienceDto scienceDto = new scienceDto();
            BeanUtils.copyProperties(t, scienceDto);
            //创建scienceImageArrayList
            List<scienceImages> list = new ArrayList<>();
            list.add(scienceImagesById);
            scienceDto.setScienceImagesList(list);
            //将scienceDto添加到sciencePage
            scienceDtoPage.getRecords().add(scienceDto);
        });
        log.info("查询成功!-{}", LocalDateTime.now());
        //存redis缓存
        if (scienceDtoPage.getTotal() != paramsKey.NUM_ZERO) {
            redisTemplate.opsForValue().set(redisKey.scienceQueryKey + redisKeyWordKey + pages, scienceDtoPage, StringCommon.TimeOut, TimeUnit.HOURS);
        } else {
            //将空的key放到队列中去
            EmptyKeyList.set(redisKey.scienceQueryKey + redisKeyWordKey + pages);
        }
        return Response.status(scienceDtoPage, SUCCESS.getCode(), SUCCESS.getMessage());
    }


    @Override
    public Response<scienceDto> getScienceById(String id) {
        //判断队列是否存在
        if (EmptyKeyList.isExist(redisKey.scienceKey + id)) {
            //返回空对象
            return Response.status(null, SUCCESS.getCode(), SUCCESS.getMessage());
        }
        scienceDto redisScienceDto = (scienceDto) redisTemplate.opsForValue().get(redisKey.scienceKey + id);
        if (!ObjectUtils.isEmpty(redisScienceDto)) {
            return Response.success(redisScienceDto, SUCCESS.getCode(), SUCCESS.getMessage());
        }
        science scienceById = baseMapper.selectById(id);
        //根据id查询科普文章对应图片资源
        LambdaQueryWrapper<scienceImages> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StringUtils.hasText(id), scienceImages::getScienceId, id);
        List<scienceImages> scienceImagesList = scienceImagesService.list(queryWrapper);
        //创建dto对象
        scienceDto scienceDto = new scienceDto();
        //将science的属性拷贝到scienceDto上
        BeanUtils.copyProperties(scienceById, scienceDto);
        //将查询的imagesList赋值给dto
        scienceDto.setScienceImagesList(scienceImagesList);
        if (!ObjectUtils.isEmpty(scienceById)) {
            log.info("查询成功!-{}", LocalDateTime.now());
            //这里还需要和scienceImage做表联查
            //存redis
            redisTemplate.opsForValue().set(redisKey.scienceKey + id, scienceDto, StringCommon.TimeOut, TimeUnit.HOURS);
            return Response.success(scienceDto, SUCCESS.getCode(), SUCCESS.getMessage());
        }
        //存该 id对应的部分未查询的状态
        EmptyKeyList.set(redisKey.scienceKey + id);
        return Response.error(null, NOT_FOUNT.getCode(), NOT_FOUNT.getMessage());
    }

    @Override
    public Response saveScienceMessage(scienceDto scienceDto) {
        //创建science对象
        science science = new science();
        BeanUtils.copyProperties(scienceDto, science, "scienceImagesList");
        //保存science信息
        science.setCreateBy(AuthThread.get());
        science.setCreateTime(LocalDateTime.now());
        int saveScienceFlag = baseMapper.insert(science);
        //拿到science的id
        boolean saveBatchScienceImageFlag = true;
        if (!scienceDto.getScienceImagesList().isEmpty()) {
            //给每个scienceImages赋scienceId
            scienceDto.getScienceImagesList().forEach(t -> {
                t.setScienceId(science.getId());
            });
            saveBatchScienceImageFlag = scienceImagesService.saveBatch(scienceDto.getScienceImagesList());
        }
        //删除对应的缓存
        redisTemplate.opsForValue().getOperations().delete(redisKey.scienceQueryKey + scienceDto.getType());
        //todo  需要改成R.status格式返回 保存对应的scienceImage信息
        return saveScienceFlag > 0 && saveBatchScienceImageFlag ? Response.success("science数据保存成功！") : Response.error("science数据保存失败!请稍后再试!");
    }

    //根据title查询数据库
    @Override
    public Response<Page<scienceDto>> getScienceByTitle(String title, Integer pages, Integer pageSize) {
        return this.getAllScienceMessage(pages, pageSize, null, title);
    }
}
